package jmine.tec.web.wicket.component.paging;

import org.apache.wicket.Component;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.navigation.paging.IPageable;
import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigation;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigationIncrementLink;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigationLink;

/**
 * PagingNavigator que extende de WebMarkupContainer - ou seja, deve ter os componentes 'inlined'
 * 
 * @author takeshi
 */
public class PagingNavigatorContainer extends WebMarkupContainer {

    /** The navigation bar to be printed, e.g. 1 | 2 | 3 etc. */
    private PagingNavigation pagingNavigation;

    private final IPageable pageable;

    private final IPagingLabelProvider labelProvider;

    /**
     * @param id String
     * @param pageable {@link IPageable}
     */
    public PagingNavigatorContainer(String id, IPageable pageable) {
        this(id, pageable, null);
    }

    /**
     * @param id String
     * @param pageable {@link IPageable}
     * @param labelProvider {@link IPagingLabelProvider}
     */
    public PagingNavigatorContainer(String id, IPageable pageable, IPagingLabelProvider labelProvider) {
        super(id);
        this.pageable = pageable;
        this.labelProvider = labelProvider;
    }

    /**
     * {@link IPageable} this navigator is linked with
     * 
     * @return {@link IPageable} instance
     */
    public final IPageable getPageable() {
        return this.pageable;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.apache.wicket.Component#onBeforeRender()
     */
    @Override
    protected void onBeforeRender() {
        if (this.get("first") == null) {
            // Get the navigation bar and add it to the hierarchy
            this.pagingNavigation = this.newNavigation(this.pageable, this.labelProvider);
            this.add(this.pagingNavigation);

            // Add additional page links
            this.add(this.newPagingNavigationLink("first", this.pageable, 0).add(new TitleAppender("PagingNavigator.first")));

            this.add(this.newPagingNavigationIncrementLink("prev", this.pageable, -1).add(new TitleAppender("PagingNavigator.previous")));

            this.add(this.newPagingNavigationIncrementLink("next", this.pageable, 1).add(new TitleAppender("PagingNavigator.next")));

            this.add(this.newPagingNavigationLink("last", this.pageable, -1).add(new TitleAppender("PagingNavigator.last")));
        }
        super.onBeforeRender();
    }

    /**
     * Create a new increment link. May be subclassed to make use of specialized links, e.g. Ajaxian links.
     * 
     * @param id the link id
     * @param pag the pageable to control
     * @param increment the increment
     * @return the increment link
     */
    protected AbstractLink newPagingNavigationIncrementLink(String id, IPageable pag, int increment) {
        return new PagingNavigationIncrementLink<Void>(id, pag, increment);
    }

    /**
     * Create a new pagenumber link. May be subclassed to make use of specialized links, e.g. Ajaxian links.
     * 
     * @param id the link id
     * @param pag the pageable to control
     * @param pageNumber the page to jump to
     * @return the pagenumber link
     */
    protected AbstractLink newPagingNavigationLink(String id, IPageable pag, int pageNumber) {
        return new PagingNavigationLink<Void>(id, pag, pageNumber);
    }

    /**
     * Create a new PagingNavigation. May be subclassed to make us of specialized PagingNavigation.
     * 
     * @param pag the pageable component
     * @param label The label provider for the link text.
     * @return the navigation object
     */
    protected PagingNavigation newNavigation(final IPageable pag, final IPagingLabelProvider label) {
        return new PagingNavigation("navigation", pag, label);
    }

    /**
     * Gets the pageable navigation component for configuration purposes.
     * 
     * @return the associated pageable navigation.
     */
    public final PagingNavigation getPagingNavigation() {
        return this.pagingNavigation;
    }

    /**
     * Appends title attribute to navigation links
     * 
     * @author igor.vaynberg
     */
    private final class TitleAppender extends AbstractBehavior {
        private static final long serialVersionUID = 1L;

        private final String resourceKey;

        /**
         * Constructor
         * 
         * @param resourceKey resource key of the message
         */
        public TitleAppender(String resourceKey) {
            this.resourceKey = resourceKey;
        }

        /** {@inheritDoc} */
        @Override
        public void onComponentTag(Component component, ComponentTag tag) {
            tag.put("title", PagingNavigatorContainer.this.getString(this.resourceKey));
        }
    }
}
